/*
 * Copyright (C) 2022, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

//
// Created by hxf on 22-8-25.
//

#include "layout-config.h"
#include "global-settings.h"
#include "screen-monitor.h"

#include <QDebug>
#include <QPushButton>
#include <QtMath>

namespace Sidebar {

static LayoutConfig *globalLayoutInstance = nullptr;
static SidebarGeometryController *globalControllerInstance = nullptr;

LayoutConfig *LayoutConfig::getInstance(QObject *parent)
{
    if (!globalLayoutInstance) {
        globalLayoutInstance = new LayoutConfig(parent);
    }

    return globalLayoutInstance;
}

LayoutConfig::LayoutConfig(QObject *parent) : QObject(parent)
{
    //平板模式布局作为默认布局
    loadTabletLayout();

    GlobalSettings *globalSetting = GlobalSettings::globalInstance();
    m_isTabletMode = globalSetting->getValue(TABLET_MODE).toBool();

    if (!m_isTabletMode) {
        loadPCLayout();
    }

    connect(globalSetting, &GlobalSettings::valueChanged, this, &LayoutConfig::updateLayout);

//    //测试布局切换功能
//    bool *isPC = new bool;
//    *isPC = !m_isTabletMode;

//    QPushButton *button = new QPushButton();
//    button->setText("点击切换");
//    button->resize(200, 200);

//    connect(button, &QPushButton::clicked, this, [=] {
//        if (*isPC) {
//            *isPC = false;
//            loadTabletLayout();

//        } else {
//            *isPC = true;
//            loadPCLayout();
//        }

//        Q_EMIT modelChanged(!(*isPC));
//    });

//    button->show();
}

bool LayoutConfig::isTabletMode()
{
    return m_isTabletMode;
}

LayoutConfig::~LayoutConfig()
{

}

void LayoutConfig::updateLayout(const QString &key)
{
    if (key == TABLET_MODE) {
        bool isTabletMode = m_isTabletMode;
        m_isTabletMode = GlobalSettings::globalInstance()->getValue(TABLET_MODE).toBool();

        if (isTabletMode == m_isTabletMode) {
            return;
        }

        Q_EMIT systemModeChanged(m_isTabletMode);
        // 1.系统模式切换后修改主窗口的大小和位置
        SidebarGeometryController::getInstance()->updateSidebarGeometrySlot();

        if (m_isTabletMode) {
            loadTabletLayout();
        } else {
            loadPCLayout();
        }
    }
}

/**
 * 修改布局为pc模式的布局，只需要修改跟平板模式不同的部分即可
 */
void LayoutConfig::loadPCLayout()
{
    // 快捷操作主体
    m_width.insert(LayoutComponent::SidebarMain, PC_SIDEBAR_WIDTH);
    m_spacing.insert(LayoutComponent::SidebarMain, 0);

    // UserInfo
    m_height.insert(LayoutComponent::SidebarUserInfo, 68);

    m_radius.insert(LayoutComponent::SidebarUserInfo, 0);
    m_spacing.insert(LayoutComponent::SidebarUserInfo, 8);
    m_margin.insert(LayoutComponent::SidebarUserInfo, {24, 0, 24, 0});

    m_width.insert(LayoutComponent::SidebarUserInfoIcon, 48);
    m_height.insert(LayoutComponent::SidebarUserInfoIcon, 48);

    m_width.insert(LayoutComponent::SidebarUserInfoPowerIcon, 48);
    m_height.insert(LayoutComponent::SidebarUserInfoPowerIcon, 48);

    // MenuButton
    m_height.insert(LayoutComponent::SidebarMenuButton, 0);
    m_height.insert(LayoutComponent::SidebarMenuButtonView, 0);

    // IconButton
    // 宽度高度随着容器改变
    m_spacing.insert(LayoutComponent::SidebarIconButton, 1);
    // 高度与宽度一致
    m_width.insert(LayoutComponent::SidebarIconButtonIcon, 48);
    m_height.insert(LayoutComponent::SidebarIconButtonView, 206);
    m_radius.insert(LayoutComponent::SidebarIconButtonView, 0);

    // ProgressBar
    m_height.insert(LayoutComponent::SidebarProgressBar, 40);
    m_radius.insert(LayoutComponent::SidebarProgressBar, 0);
    m_spacing.insert(LayoutComponent::SidebarProgressBar, 8);
    m_margin.insert(LayoutComponent::SidebarProgressBar, {24, 0, 24, 0});

    m_width.insert(LayoutComponent::SidebarProgressBarIcon, 16);
    m_height.insert(LayoutComponent::SidebarProgressBarIcon, 16);

    m_height.insert(LayoutComponent::SidebarProgressBarSlider, 16);
    m_radius.insert(LayoutComponent::SidebarProgressBarSlider, 8);

    m_spacing.insert(LayoutComponent::SidebarProgressBarView, 0);

    // SidebarWeather
    m_height.insert(LayoutComponent::SidebarWeather, 32);
    m_spacing.insert(LayoutComponent::SidebarWeather, 8);
    m_margin.insert(LayoutComponent::SidebarWeather, {24, 0, 24, 0});

    // SidebarFoldShortcutArea
    m_height.insert(LayoutComponent::SidebarFoldShortcutArea, 24);
    m_radius.insert(LayoutComponent::SidebarFoldShortcutArea, 12);

    m_width.insert(LayoutComponent::NotificationItem, 0);
    m_height.insert(LayoutComponent::NotificationItem, 108);
    m_radius.insert(LayoutComponent::NotificationItem, 6);
    m_spacing.insert(LayoutComponent::NotificationItem, 0);
    m_margin.insert(LayoutComponent::NotificationItem, {16, 16, 16, 4});

    m_height.insert(LayoutComponent::NotificationItemNormal, 20);
    m_height.insert(LayoutComponent::NotificationItemBody, 24);


    Q_EMIT layoutChanged();
}

void LayoutConfig::loadTabletLayout()
{
    // 快捷操作主体
    m_width.insert(LayoutComponent::SidebarMain, TABLET_SIDEBAR_WIDTH);
    m_spacing.insert(LayoutComponent::SidebarMain, 16);

    // UserInfo
    m_height.insert(LayoutComponent::SidebarUserInfo, 128);
    m_radius.insert(LayoutComponent::SidebarUserInfo, 32);
    m_spacing.insert(LayoutComponent::SidebarUserInfo, 8);
    m_margin.insert(LayoutComponent::SidebarUserInfo, {32, 0, 32, 0});

    m_width.insert(LayoutComponent::SidebarUserInfoIcon, 80);
    m_height.insert(LayoutComponent::SidebarUserInfoIcon, 80);

    m_width.insert(LayoutComponent::SidebarUserInfoPowerIcon, 64);
    m_height.insert(LayoutComponent::SidebarUserInfoPowerIcon, 64);

    // MenuButton
    m_height.insert(LayoutComponent::SidebarMenuButton, 128);
    m_radius.insert(LayoutComponent::SidebarMenuButton, 32);
    m_spacing.insert(LayoutComponent::SidebarMenuButton, 8);
    m_margin.insert(LayoutComponent::SidebarMenuButton, {32, 0, 8, 0});

    m_height.insert(LayoutComponent::SidebarMenuButtonView, 128);
    m_spacing.insert(LayoutComponent::SidebarMenuButtonView, 16);

    // IconButton
    // 宽度高度随着容器改变
    m_spacing.insert(LayoutComponent::SidebarIconButton, 8);
    // 高度与宽度一致
    m_width.insert(LayoutComponent::SidebarIconButtonIcon, 64);

    m_height.insert(LayoutComponent::SidebarIconButtonView, 256);
    m_radius.insert(LayoutComponent::SidebarIconButtonView, 32);
    m_margin.insert(LayoutComponent::SidebarIconButtonView, {0, 24, 0, 24});

    // ProgressBar
    m_height.insert(LayoutComponent::SidebarProgressBar, 112);
    m_radius.insert(LayoutComponent::SidebarProgressBar, 32);
    m_spacing.insert(LayoutComponent::SidebarProgressBar, 16);
    m_margin.insert(LayoutComponent::SidebarProgressBar, {32, 0, 32, 0});

    m_width.insert(LayoutComponent::SidebarProgressBarIcon, 32);
    m_height.insert(LayoutComponent::SidebarProgressBarIcon, 32);

    m_height.insert(LayoutComponent::SidebarProgressBarSlider, 48);
    m_radius.insert(LayoutComponent::SidebarProgressBarSlider, 16);

    m_spacing.insert(LayoutComponent::SidebarProgressBarView, 16);

    // SidebarWeather
    m_height.insert(LayoutComponent::SidebarWeather, 0);

    // SidebarFoldShortcutArea
    m_height.insert(LayoutComponent::SidebarFoldShortcutArea, 0);

    Q_EMIT layoutChanged();
}

int LayoutConfig::width(LayoutComponent::Component component)
{
    if (m_width.contains(component)) {
        return m_width.value(component);
    }

    return 0;
}

int LayoutConfig::height(LayoutComponent::Component component)
{
    if (m_height.contains(component)) {
        return m_height.value(component);
    }

    return 0;
}

int LayoutConfig::radius(LayoutComponent::Component component)
{
    if (m_radius.contains(component)) {
        return m_radius.value(component);
    }

    return 0;
}

int LayoutConfig::spacing(LayoutComponent::Component component)
{
    if (m_spacing.contains(component)) {
        return m_spacing.value(component);
    }

    return 0;
}

int LayoutConfig::margin(LayoutComponent::Component component, int position)
{
    if (m_margin.contains(component)) {
        switch (position) {
            case 0: return m_margin.value(component).left;
            case 1: return m_margin.value(component).top;
            case 2: return m_margin.value(component).right;
            case 3: return m_margin.value(component).bottom;
            default:
                break;
        }
    }

    return 0;
}

LayoutHelper::LayoutHelper(QObject *parent) : QObject(parent)
{
    m_layoutConfig = LayoutConfig::getInstance();
    if (m_layoutConfig) {
        connect(m_layoutConfig, &LayoutConfig::layoutChanged, this, &LayoutHelper::layoutChanged);
    }
}

void LayoutHelper::setComponent(LayoutComponent::Component component)
{
    m_component = component;
    Q_EMIT componentChanged();
    Q_EMIT layoutChanged();
}

LayoutComponent::Component LayoutHelper::getComponent()
{
    return m_component;
}

int LayoutHelper::getWidth()
{
    return m_layoutConfig->width(m_component);
}

int LayoutHelper::getHeight()
{
    return m_layoutConfig->height(m_component);
}

int LayoutHelper::getRadius()
{
    return m_layoutConfig->radius(m_component);
}

int LayoutHelper::getSpacing()
{
    return m_layoutConfig->spacing(m_component);
}

int LayoutHelper::getLeftMargin()
{
    return m_layoutConfig->margin(m_component, 0);
}

int LayoutHelper::getTopMargin()
{
    return m_layoutConfig->margin(m_component, 1);
}

int LayoutHelper::getRightMargin()
{
    return m_layoutConfig->margin(m_component, 2);
}

int LayoutHelper::getBottomMargin()
{
    return m_layoutConfig->margin(m_component, 3);
}

SidebarGeometryController *SidebarGeometryController::getInstance(QObject *parent)
{
    if (!globalControllerInstance) {
        globalControllerInstance = new SidebarGeometryController(parent);
    }

    return globalControllerInstance;
}

SidebarGeometryController::SidebarGeometryController(QObject *parent) : QObject(parent)
{
    updateSidebarGeometrySlot();

    ScreenMonitor *screenMonitor = ScreenMonitor::getInstance();
    connect(screenMonitor, &ScreenMonitor::geometryChanged, this, &SidebarGeometryController::updateSidebarGeometrySlot);
    connect(screenMonitor, &ScreenMonitor::primaryScreenChanged, this, &SidebarGeometryController::updateSidebarGeometrySlot);
    connect(screenMonitor, &ScreenMonitor::panelPropertyChanged, this, &SidebarGeometryController::updateSidebarGeometrySlot);
    connect(GlobalSettings::globalInstance(), &GlobalSettings::valueChanged,
            this, [=] (const QString &key) {
            if (key == USD_SCALING_FACTOR_KEY && !LayoutConfig::getInstance()->isTabletMode()) {
                updateSidebarGeometrySlot();
            }
    });
}

qint32 SidebarGeometryController::sidebarWindowPadding()
{
    return m_padding;
}

qint32 SidebarGeometryController::minimumThreshold()
{
    return m_minimumThreshold;
}

qint32 SidebarGeometryController::primaryScreenRight()
{
    return m_primaryScreenRight;
}

QRect SidebarGeometryController::sidebarWindowGeometry()
{
    return m_sidebarWindowGeometry;
}

void SidebarGeometryController::updateSidebarGeometrySlot()
{
    m_isTabletMode = LayoutConfig::getInstance()->isTabletMode();
    QRect screenRect = ScreenMonitor::getInstance()->getGeometry();

    // 8%的屏幕宽度为最小滑动距离
    m_minimumThreshold   = static_cast<qint32>(static_cast<qreal>(screenRect.width()) * 0.08);
    m_primaryScreenRight = screenRect.right();

    // 平板模式下为全屏，暂不需要考虑任务栏影响
    if (!m_isTabletMode) {
        // 1.排除任务栏的干扰
        excludePanel(screenRect);
        // 2.调整窗口位置
        relocationSidebar(screenRect);
        // 3.调整窗口大小
        resizeSidebar(screenRect);
    }

    m_sidebarWindowGeometry = screenRect;
    resizeContent(screenRect);
//    qDebug() << "---updateSidebarGeometrySlot:" << m_sidebarWindowGeometry << m_sidebarContentGeometry;

    Q_EMIT geometryChanged();
}

void SidebarGeometryController::excludePanel(QRect& rect) const
{
    ScreenMonitor *screenMonitor = ScreenMonitor::getInstance();
    int panelPosition = screenMonitor->getPanelPosition();
    double scale = GlobalSettings::globalInstance()->getValue(USD_SCALING_FACTOR_KEY).toDouble();
    int panelSize = qCeil(screenMonitor->getPanelSize() * scale);
    //qDebug() << "excludePanel" << scale << m_isTabletMode << panelSize;

    // 任务栏位置 上: 1, 下: 0, 左: 2, 右: 3
    switch(panelPosition) {
        case 0:
            rect.setHeight(rect.height() - panelSize);
            break;
        case 1:
            rect = QRect(rect.x(), (rect.y() + panelSize), rect.width(), (rect.height() - panelSize));
            break;
        case 2:
            rect = QRect((rect.x() + panelSize), rect.y(), (rect.width() - panelSize), rect.height());
            break;
        case 3:
            rect.setWidth(rect.width() - panelSize);
            break;
        default:
            break;
    }
}

void SidebarGeometryController::relocationSidebar(QRect &rect) const
{
    rect.setX(rect.right() - (PC_SIDEBAR_WIDTH + m_padding * 2) + 1);
}

void SidebarGeometryController::resizeSidebar(QRect &rect) const
{
    rect.setWidth(PC_SIDEBAR_WIDTH + m_padding * 2);
}

void SidebarGeometryController::resizeContent(QRect &sidebarRect)
{
    int sidebarWidth;
    if (m_isTabletMode) {
        sidebarWidth = TABLET_SIDEBAR_WIDTH + m_padding * 2;
        m_sidebarContentGeometry.setX(sidebarRect.width() - sidebarWidth + m_padding);

    } else {
        sidebarWidth = sidebarRect.width();
        m_sidebarContentGeometry.setX(m_padding);
    }

    m_sidebarContentGeometry.setY(m_padding);
    m_sidebarContentGeometry.setWidth(sidebarWidth - (m_padding * 2));
    m_sidebarContentGeometry.setHeight(sidebarRect.height() - (m_padding * 2));
}

QRect SidebarGeometryController::sidebarContentGeometry()
{
    return m_sidebarContentGeometry;
}

void SidebarGeometryController::updateWindowGeometry(QWindow *window)
{
    if (!window) {
        qWarning() << "SidebarGeometryController::updateWindowGeometry target window is null.";
        return;
    }

    window->setGeometry(m_sidebarWindowGeometry);
}

} // UkuiShortcut
